package com.copa.aop;

import com.copa.annotation.Log;
import com.copa.module.system.domain.entity.AdminLogEntity;
import com.copa.module.system.service.LogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author copa
 * @createDate 2021-02-25 14:53
 * @function @Log切面处理
 */
@Component
@Aspect
@Slf4j
public class LogAspect {

    @Autowired
    private LogService logService;

    private long currentTime = 0L;


    @Pointcut("@annotation(com.copa.annotation.Log)")
    public void logPointCut(){}

    /**
     * 配置环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        AdminLogEntity log = getLog(proceedingJoinPoint);

        currentTime = System.currentTimeMillis();
        Object returnValue = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();

        log.setTime(endTime - currentTime);

        logService.insert(log);

        return returnValue;

    }

    private AdminLogEntity getLog(ProceedingJoinPoint proceedingJoinPoint) {

        //获取操作管理员
        String optAdmin = null;
        String ip = null;
        /*try{
            XuejianAdmin admin = Optional.ofNullable(((XuejianAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal())).orElse(new XuejianAdmin());
            optAdmin = admin.getUsername();
        }catch (Exception e){
            log.info(e.getMessage());
        }*/


        //获取 request
        //HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        //String ip = request.getRemoteAddr();

        StringBuilder params = new StringBuilder("{");
        //参数值
        Object[] argValues = proceedingJoinPoint.getArgs();
        //参数名称
        String[] argNames = ((MethodSignature)proceedingJoinPoint.getSignature()).getParameterNames();
        if(argValues != null){
            for (int i = 0; i < argValues.length; i++) {
//                if("adminId".equals(argNames[i])){
//                    ResponseMessage<XuejianAdmin> adminRsg = adminService.find((Integer) argValues[i]);
//                    optAdmin = adminRsg.getData().getUsername();
//                    ip = adminRsg.getData().getLastLoginIp();
//                    continue;
//                }
//                if("password".equals(argNames[i])){
//                    continue;
//                }
                params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
            }
        }
        params.append(" }");

        //获取 Log注解描述
        MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        Log annotation = method.getAnnotation(Log.class);
        String desc = annotation.value();

        // 方法路径
        String methodName = proceedingJoinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";

        return AdminLogEntity.builder()
                .description(desc)
                .method(methodName)
                .params(params.toString())
                .logType("INFO")
//                .requestIp(ip)
                .username(optAdmin).build();
    }

    /**
     * 异常通知
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "logPointCut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        AdminLogEntity log = getLog((ProceedingJoinPoint) joinPoint);
        log.setTime(System.currentTimeMillis() - currentTime);
        log.setExceptionDetail(e.getMessage());
        log.setLogType("ERROR");
        logService.insert(log);
    }
}
